<!DOCTYPE html>
<html lang='zh-CN'>

<head>
  <meta name="generator" content="Hexo 6.3.0">
  <meta name="hexo-theme" content="https://github.com/xaoxuu/hexo-theme-stellar/tree/1.19.0">
  <meta charset="utf-8">
  

  <meta http-equiv='x-dns-prefetch-control' content='on' />
  <link rel='dns-prefetch' href='https://gcore.jsdelivr.net'>
  <link rel="preconnect" href="https://gcore.jsdelivr.net" crossorigin>
  <link rel='dns-prefetch' href='//unpkg.com'>

  <meta name="renderer" content="webkit">
  <meta name="force-rendering" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="HandheldFriendly" content="True" >
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="theme-color" content="#f8f8f8">
  
  <title>Swagger接口文档使用 - 愔颂</title>

  
    <meta name="description" content="Spring Boot集成Swagger显示后端服务方法RestFul接口文档、方便功能测试和前端联调。">
<meta property="og:type" content="article">
<meta property="og:title" content="Swagger接口文档使用">
<meta property="og:url" content="https://farhills.gitee.io/2023/10/05/Swagger%E6%8E%A5%E5%8F%A3%E6%96%87%E6%A1%A3%E4%BD%BF%E7%94%A8/index.html">
<meta property="og:site_name" content="愔颂">
<meta property="og:description" content="Spring Boot集成Swagger显示后端服务方法RestFul接口文档、方便功能测试和前端联调。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464252-81f3cc72-a6fa-4f44-9c29-c029d13f8572.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868883805-531893c7-717d-4d21-8595-156e5a01f778.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685869112559-38d39412-a9ce-40ff-967b-bd3ac3ce0857.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464267-37e7b8e1-c50c-463a-b01f-19e2103b6288.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464191-0d0663f6-2719-4c02-bdbd-1d363d2d92df.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464255-60f4cad9-6240-4bfb-b7ae-ea2d04c968bf.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464223-b2b09c64-5ab3-4710-ba5d-8e799f2333e9.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464702-154bdb29-e615-421b-96a0-7a65020e6f58.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464785-0cf4291f-5d64-4623-bcab-652e579ffd4b.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464807-5270bd80-86aa-4e19-8b07-2ae6e732f97f.png">
<meta property="article:published_time" content="2023-10-05T03:13:35.024Z">
<meta property="article:modified_time" content="2023-10-04T07:24:29.866Z">
<meta property="article:author" content="远岫">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464252-81f3cc72-a6fa-4f44-9c29-c029d13f8572.png">
  
  
  
  

  <!-- feed -->
  

  
    
<link rel="stylesheet" href="/css/main.css">

  

  
    <link rel="shortcut icon" href="https://z1.ax1x.com/2023/10/05/pPXijyT.png">
  

  

  


  
</head>

<body>
  




  <div class='l_body' id='start'>
    <aside class='l_left' layout='post'>
    

  

<header class="header"><div class="logo-wrap"><a class="avatar" href="/about/"><div class="bg" style="opacity:0;background-image:url(https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.4/avatar/round/rainbow64@3x.webp);"></div><img no-lazy class="avatar" src="https://s1.ax1x.com/2022/11/12/ziJjfK.jpg" onerror="javascript:this.classList.add('error');this.src='https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.4/image/2659360.svg';"></a><a class="title" href="/"><div class="main" ff="title">愔颂</div></a></div>

<nav class="menu dis-select"><a class="nav-item active" href="/">文章</a><a class="nav-item" href="/friends/">收藏</a><a class="nav-item" href="/about/">关于</a></nav>
</header>


<div class="widgets">
<widget class="widget-wrapper search"><div class="widget-body"><div class="search-wrapper" id="search"><form class="search-form"><input type="text" class="search-input" id="search-input" data-filter="/blog/" placeholder="文章搜索"><svg t="1670596976048" class="icon search-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2676" width="200" height="200"><path d="M938.2 832.6L723.8 618.1c-2.5-2.5-5.3-4.4-7.9-6.4 36.2-55.6 57.3-121.8 57.3-193.1C773.3 222.8 614.6 64 418.7 64S64 222.8 64 418.6c0 195.9 158.8 354.6 354.6 354.6 71.3 0 137.5-21.2 193.2-57.4 2 2.7 3.9 5.4 6.3 7.8L832.5 938c14.6 14.6 33.7 21.9 52.8 21.9 19.1 0 38.2-7.3 52.8-21.8 29.2-29.1 29.2-76.4 0.1-105.5M418.7 661.3C284.9 661.3 176 552.4 176 418.6 176 284.9 284.9 176 418.7 176c133.8 0 242.6 108.9 242.6 242.7 0 133.7-108.9 242.6-242.6 242.6" p-id="2677"></path></svg></form><div id="search-result"></div><div class="search-no-result">没有找到内容！</div></div></div></widget>


<widget class="widget-wrapper toc single" id="data-toc"><div class="widget-header cap dis-select"><span class="name">Swagger接口文档使用</span></div><div class="widget-body fs14"><div class="doc-tree active"><ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81Swagger%E7%AE%80%E4%BB%8B"><span class="toc-text">1、Swagger简介</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2%E3%80%81SpringBoot%E9%9B%86%E6%88%90Swagger"><span class="toc-text">2、SpringBoot集成Swagger</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3%E3%80%81%E9%85%8D%E7%BD%AESwagger"><span class="toc-text">3、配置Swagger</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1%E3%80%81%E5%88%9D%E6%AD%A5%E9%9B%86%E6%88%90"><span class="toc-text">3.1、初步集成</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2%E3%80%81%E9%85%8D%E7%BD%AE%E6%89%AB%E6%8F%8F%E6%8E%A5%E5%8F%A3"><span class="toc-text">3.2、配置扫描接口</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3%E3%80%81%E9%85%8D%E7%BD%AESwagger%E5%BC%80%E5%85%B3"><span class="toc-text">3.3、配置Swagger开关</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4%E3%80%81%E9%85%8D%E7%BD%AEAPI%E5%88%86%E7%BB%84"><span class="toc-text">3.4、配置API分组</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-5%E3%80%81%E5%AE%9E%E4%BD%93%E9%85%8D%E7%BD%AE"><span class="toc-text">3.5、实体配置</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-6%E3%80%81%E5%B8%B8%E7%94%A8%E6%B3%A8%E8%A7%A3"><span class="toc-text">3.6、常用注解</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-7%E3%80%81%E6%8B%93%E5%B1%95%EF%BC%9A%E5%85%B6%E4%BB%96%E7%9A%AE%E8%82%A4"><span class="toc-text">3.7、拓展：其他皮肤</span></a></li></ol></li></ol></div></div></widget>




</div>


    </aside>
    <div class='l_main'>
      

      



<div class="bread-nav fs12"><div id="breadcrumb"><a class="cap breadcrumb" href="/">主页</a><span class="sep"></span><a class="cap breadcrumb" href="/">文章</a><span class="sep"></span><a class="cap breadcrumb-link" href="/categories/Spring-Boot/">Spring Boot</a></div><div id="post-meta">发布于&nbsp;<time datetime="2023-10-05T03:13:35.024Z">2023-10-05</time></div></div>

<article class='md-text content post'>
<h1 class="article-title"><span>Swagger接口文档使用</span></h1>
<meta name="referrer" content="no-referrer"/>

<p>Spring Boot集成Swagger显示后端服务方法RestFul接口文档、方便功能测试和前端联调。</p>
<span id="more"></span>

<h3 id="1、Swagger简介"><a href="#1、Swagger简介" class="headerlink" title="1、Swagger简介"></a>1、Swagger简介</h3><hr>
<p><strong>前后端分离</strong></p>
<ul>
<li><p>前端 -&gt; 前端控制层、视图层</p>
</li>
<li><p>后端 -&gt; 后端控制层、服务层、数据访问层</p>
</li>
<li><p>前后端通过API进行交互</p>
</li>
<li><p>前后端相对独立且松耦合</p>
</li>
</ul>
<p><strong>产生的问题</strong></p>
<ul>
<li>前后端集成，前端或者后端无法做到“及时协商，尽早解决”，最终导致问题集中爆发。</li>
</ul>
<p><strong>解决方案</strong></p>
<p>首先定义schema [ 计划的提纲 ]，并实时跟踪最新的API，降低集成风险。</p>
<p><strong>Swagger</strong></p>
<ul>
<li>号称世界上最流行的API框架</li>
<li>Restful Api 文档在线自动生成器 &#x3D;&gt; <strong>API 文档 与API 定义同步更新</strong></li>
<li>直接运行，在线测试API</li>
<li>支持多种语言 （如：Java，PHP等）</li>
<li>官网：<a target="_blank" rel="noopener" href="https://swagger.io/">https://swagger.io/</a></li>
</ul>
<h3 id="2、SpringBoot集成Swagger"><a href="#2、SpringBoot集成Swagger" class="headerlink" title="2、SpringBoot集成Swagger"></a>2、SpringBoot集成Swagger</h3><hr>
<p><strong>SpringBoot集成Swagger</strong> &#x3D;&gt; <strong>springfox</strong>，两个jar包</p>
<ul>
<li><strong>Springfox-swagger2</strong></li>
<li>swagger-springmvc</li>
</ul>
<p>要求：jdk 1.8 + 否则swagger2无法运行</p>
<p>步骤：</p>
<p>1、新建一个SpringBoot-web项目</p>
<p>2、添加Maven依赖</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">   &lt;groupId&gt;io.springfox&lt;/groupId&gt;</span><br><span class="line">   &lt;artifactId&gt;springfox-swagger2&lt;/artifactId&gt;</span><br><span class="line">   &lt;version&gt;2.9.2&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br><span class="line">&lt;!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">   &lt;groupId&gt;io.springfox&lt;/groupId&gt;</span><br><span class="line">   &lt;artifactId&gt;springfox-swagger-ui&lt;/artifactId&gt;</span><br><span class="line">   &lt;version&gt;2.9.2&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>

<p>注：swagger2.9.2版本需要在spring boot2.6之前的版本才能完美运行。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;</span><br><span class="line">&lt;version&gt;2.5.7&lt;/version&gt;</span><br></pre></td></tr></table></figure>



<p>3、编写HelloController，测试确保运行成功！</p>
<p>4、要使用Swagger，我们需要编写一个配置类-SwaggerConfig来配置 Swagger</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">@Configuration //配置类</span><br><span class="line">@EnableSwagger2// 开启Swagger2的自动配置</span><br><span class="line">public class SwaggerConfig &#123;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>5、访问测试 ：<a target="_blank" rel="noopener" href="http://localhost:8080/swagger-ui.html">http://localhost:8080/swagger-ui.html</a> ，可以看到swagger的界面；</p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464252-81f3cc72-a6fa-4f44-9c29-c029d13f8572.png" fancybox="true"/></div></div>



<h3 id="3、配置Swagger"><a href="#3、配置Swagger" class="headerlink" title="3、配置Swagger"></a>3、配置Swagger</h3><hr>
<h4 id="3-1、初步集成"><a href="#3-1、初步集成" class="headerlink" title="3.1、初步集成"></a>3.1、初步集成</h4><p>1、Swagger实例Bean是Docket，所以通过配置Docket实例来配置Swaggger。</p>
<p>在SwaggerConfig类中添加如下代码：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">@Bean //配置docket以配置Swagger具体参数</span><br><span class="line">public Docket docket() &#123;</span><br><span class="line">   return new Docket(DocumentationType.SWAGGER_2);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>2、可以通过apiInfo()属性配置文档信息</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">//配置文档信息</span><br><span class="line">private ApiInfo apiInfo() &#123;</span><br><span class="line">   Contact contact = new Contact(&quot;联系人名字&quot;, &quot;http://xxx.xxx.com/联系人访问链接&quot;, &quot;联系人邮箱&quot;);</span><br><span class="line">   return new ApiInfo(</span><br><span class="line">           &quot;Swagger学习&quot;, // 标题</span><br><span class="line">           &quot;学习演示如何配置Swagger&quot;, // 描述</span><br><span class="line">           &quot;v1.0&quot;, // 版本</span><br><span class="line">           &quot;http://terms.service.url/组织链接&quot;, // 组织链接</span><br><span class="line">           contact, // 联系人信息</span><br><span class="line">           &quot;Apach 2.0 许可&quot;, // 许可</span><br><span class="line">           &quot;许可链接&quot;, // 许可连接</span><br><span class="line">           new ArrayList&lt;&gt;()// 扩展</span><br><span class="line">  );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>3、Docket 实例关联上 apiInfo()</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">@Bean</span><br><span class="line">public Docket docket() &#123;</span><br><span class="line">   return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>4、重启项目，访问测试 <a target="_blank" rel="noopener" href="http://localhost:8080/swagger-ui.html">http://localhost:8080/swagger-ui.html</a>  看下效果；</p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868883805-531893c7-717d-4d21-8595-156e5a01f778.png" fancybox="true"/></div></div>

<h4 id="3-2、配置扫描接口"><a href="#3-2、配置扫描接口" class="headerlink" title="3.2、配置扫描接口"></a>3.2、配置扫描接口</h4><p>1、构建Docket时通过select()方法配置怎么扫描接口。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">@Bean</span><br><span class="line">public Docket docket() &#123;</span><br><span class="line">   return new Docket(DocumentationType.SWAGGER_2)</span><br><span class="line">      .apiInfo(apiInfo())</span><br><span class="line">      .select()// 通过.select()方法，去配置扫描接口,RequestHandlerSelectors配置如何扫描接口</span><br><span class="line">      .apis(RequestHandlerSelectors.basePackage(&quot;com.example.swaggertest.controller&quot;))</span><br><span class="line">      .build();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>2、重启项目测试，由于我们配置根据包的路径扫描接口，所以我们只能看到一个类</p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685869112559-38d39412-a9ce-40ff-967b-bd3ac3ce0857.png" fancybox="true"/></div></div>

<p>3、除了通过包路径配置扫描接口外，还可以通过配置其他方式扫描接口：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">any() <span class="comment">// 扫描所有，项目中的所有接口都会被扫描到</span></span><br><span class="line">none() <span class="comment">// 不扫描接口</span></span><br><span class="line"><span class="comment">// 通过方法上的注解扫描，如withMethodAnnotation(GetMapping.class)只扫描get请求</span></span><br><span class="line">withMethodAnnotation(<span class="keyword">final</span> Class&lt;? <span class="keyword">extends</span> <span class="title class_">Annotation</span>&gt; annotation)</span><br><span class="line"><span class="comment">// 通过类上的注解扫描，如.withClassAnnotation(Controller.class)只扫描有controller注解的类中的接口</span></span><br><span class="line">withClassAnnotation(<span class="keyword">final</span> Class&lt;? <span class="keyword">extends</span> <span class="title class_">Annotation</span>&gt; annotation)</span><br><span class="line">basePackage(<span class="keyword">final</span> String basePackage) <span class="comment">// 根据包路径扫描接口</span></span><br></pre></td></tr></table></figure>

<p>4、除此之外，我们还可以配置接口扫描过滤：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> Docket <span class="title function_">docket</span><span class="params">()</span> &#123;</span><br><span class="line">   <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Docket</span>(DocumentationType.SWAGGER_2)</span><br><span class="line">      .apiInfo(apiInfo())</span><br><span class="line">      .select()<span class="comment">// 通过.select()方法，去配置扫描接口,RequestHandlerSelectors配置如何扫描接口</span></span><br><span class="line">      .apis(RequestHandlerSelectors.basePackage(<span class="string">&quot;com.kuang.swagger.controller&quot;</span>))</span><br><span class="line">       <span class="comment">// 配置如何通过path过滤,即这里只扫描请求以/kuang开头的接口</span></span><br><span class="line">      .paths(PathSelectors.ant(<span class="string">&quot;/kuang/**&quot;</span>))</span><br><span class="line">      .build();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>5、这里的可选值还有</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">any() <span class="comment">// 任何请求都扫描</span></span><br><span class="line">none() <span class="comment">// 任何请求都不扫描</span></span><br><span class="line">regex(<span class="keyword">final</span> String pathRegex) <span class="comment">// 通过正则表达式控制</span></span><br><span class="line">ant(<span class="keyword">final</span> String antPattern) <span class="comment">// 通过ant()控制</span></span><br></pre></td></tr></table></figure>

<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464267-37e7b8e1-c50c-463a-b01f-19e2103b6288.png" fancybox="true"/></div></div>



<h4 id="3-3、配置Swagger开关"><a href="#3-3、配置Swagger开关" class="headerlink" title="3.3、配置Swagger开关"></a>3.3、配置Swagger开关</h4><p>1、通过enable()方法配置是否启用swagger，如果是false，swagger将不能在浏览器中访问了</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> Docket <span class="title function_">docket</span><span class="params">()</span> &#123;</span><br><span class="line">   <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Docket</span>(DocumentationType.SWAGGER_2)</span><br><span class="line">      .apiInfo(apiInfo())</span><br><span class="line">      .enable(<span class="literal">false</span>) <span class="comment">//配置是否启用Swagger，如果是false，在浏览器将无法访问</span></span><br><span class="line">      .select()<span class="comment">// 通过.select()方法，去配置扫描接口,RequestHandlerSelectors配置如何扫描接口</span></span><br><span class="line">      .apis(RequestHandlerSelectors.basePackage(<span class="string">&quot;com.kuang.swagger.controller&quot;</span>))</span><br><span class="line">       <span class="comment">// 配置如何通过path过滤,即这里只扫描请求以/kuang开头的接口</span></span><br><span class="line">      .paths(PathSelectors.ant(<span class="string">&quot;/kuang/**&quot;</span>))</span><br><span class="line">      .build();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>2、如何动态配置当项目处于test、dev环境时显示swagger，处于prod时不显示？</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> Docket <span class="title function_">docket</span><span class="params">(Environment environment)</span> &#123;</span><br><span class="line">   <span class="comment">// 设置要显示swagger的环境</span></span><br><span class="line">   <span class="type">Profiles</span> <span class="variable">of</span> <span class="operator">=</span> Profiles.of(<span class="string">&quot;dev&quot;</span>, <span class="string">&quot;test&quot;</span>);</span><br><span class="line">   <span class="comment">// 判断当前是否处于该环境</span></span><br><span class="line">   <span class="comment">// 通过 enable() 接收此参数判断是否要显示</span></span><br><span class="line">   <span class="type">boolean</span> <span class="variable">b</span> <span class="operator">=</span> environment.acceptsProfiles(of);</span><br><span class="line">   </span><br><span class="line">   <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Docket</span>(DocumentationType.SWAGGER_2)</span><br><span class="line">      .apiInfo(apiInfo())</span><br><span class="line">      .enable(b) <span class="comment">//配置是否启用Swagger，如果是false，在浏览器将无法访问</span></span><br><span class="line">      .select()<span class="comment">// 通过.select()方法，去配置扫描接口,RequestHandlerSelectors配置如何扫描接口</span></span><br><span class="line">      .apis(RequestHandlerSelectors.basePackage(<span class="string">&quot;com.kuang.swagger.controller&quot;</span>))</span><br><span class="line">       <span class="comment">// 配置如何通过path过滤,即这里只扫描请求以/jun开头的接口</span></span><br><span class="line">      .paths(PathSelectors.ant(<span class="string">&quot;/jun/**&quot;</span>))</span><br><span class="line">      .build();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>3、可以在项目中增加一个dev的配置文件查看效果！</p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464191-0d0663f6-2719-4c02-bdbd-1d363d2d92df.png" fancybox="true"/></div></div>



<h4 id="3-4、配置API分组"><a href="#3-4、配置API分组" class="headerlink" title="3.4、配置API分组"></a>3.4、配置API分组</h4><div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464255-60f4cad9-6240-4bfb-b7ae-ea2d04c968bf.png" fancybox="true"/></div></div>

<p>1、如果没有配置分组，默认是default。通过groupName()方法即可配置分组：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> Docket <span class="title function_">docket</span><span class="params">(Environment environment)</span> &#123;</span><br><span class="line">   <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Docket</span>(DocumentationType.SWAGGER_2).apiInfo(apiInfo())</span><br><span class="line">      .groupName(<span class="string">&quot;hello&quot;</span>) <span class="comment">// 配置分组</span></span><br><span class="line">       <span class="comment">// 省略配置....</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>2、重启项目查看分组</p>
<p>3、如何配置多个分组？配置多个分组只需要配置多个docket即可：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> Docket <span class="title function_">docket1</span><span class="params">()</span>&#123;</span><br><span class="line">   <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Docket</span>(DocumentationType.SWAGGER_2).groupName(<span class="string">&quot;group1&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> Docket <span class="title function_">docket2</span><span class="params">()</span>&#123;</span><br><span class="line">   <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Docket</span>(DocumentationType.SWAGGER_2).groupName(<span class="string">&quot;group2&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> Docket <span class="title function_">docket3</span><span class="params">()</span>&#123;</span><br><span class="line">   <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Docket</span>(DocumentationType.SWAGGER_2).groupName(<span class="string">&quot;group3&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>4、重启项目查看即可</p>
<h4 id="3-5、实体配置"><a href="#3-5、实体配置" class="headerlink" title="3.5、实体配置"></a>3.5、实体配置</h4><p>1、新建一个实体类</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@ApiModel(&quot;用户实体&quot;)</span><br><span class="line">public class User &#123;</span><br><span class="line">   @ApiModelProperty(&quot;用户名&quot;)</span><br><span class="line">   public String username;</span><br><span class="line">   @ApiModelProperty(&quot;密码&quot;)</span><br><span class="line">   public String password;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>2、只要这个实体在<strong>请求接口</strong>的返回值上（即使是泛型），都能映射到实体项中：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">@RequestMapping(&quot;/getUser&quot;)</span><br><span class="line">public User getUser()&#123;</span><br><span class="line">   return new User();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>3、重启查看测试</p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464223-b2b09c64-5ab3-4710-ba5d-8e799f2333e9.png" fancybox="true"/></div></div>

<p>注：并不是因为@ApiModel这个注解让实体显示在这里了，而是只要出现在接口方法的返回值上的实体都会显示在这里，而@ApiModel和@ApiModelProperty这两个注解只是为实体添加注释的。</p>
<p>@ApiModel为类添加注释</p>
<p>@ApiModelProperty为类属性添加注释</p>
<h4 id="3-6、常用注解"><a href="#3-6、常用注解" class="headerlink" title="3.6、常用注解"></a>3.6、常用注解</h4><p>Swagger的所有注解定义在io.swagger.annotations包下</p>
<p>下面列一些经常用到的，未列举出来的可以另行查阅说明：</p>
<table>
<thead>
<tr>
<th>Swagger注解</th>
<th>简单说明</th>
</tr>
</thead>
<tbody><tr>
<td>@Api(tags &#x3D; “xxx模块说明”)</td>
<td>作用在模块类上</td>
</tr>
<tr>
<td>@ApiOperation(“xxx接口说明”)</td>
<td>作用在接口方法上</td>
</tr>
<tr>
<td>@ApiModel(“xxxPOJO说明”)</td>
<td>作用在模型类上：如VO、BO</td>
</tr>
<tr>
<td>@ApiModelProperty(value &#x3D; “xxx属性说明”,hidden &#x3D; true)</td>
<td>作用在类方法和属性上，hidden设置为true可以隐藏该属性</td>
</tr>
<tr>
<td>@ApiParam(“xxx参数说明”)</td>
<td>作用在参数、方法和字段上，类似@ApiModelProperty</td>
</tr>
</tbody></table>
<p>我们也可以给请求的接口配置一些注释</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ApiOperation(&quot;xxx的接口&quot;)</span></span><br><span class="line"><span class="meta">@PostMapping(&quot;/jun&quot;)</span></span><br><span class="line"><span class="meta">@ResponseBody</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">test</span><span class="params">(<span class="meta">@ApiParam(&quot;这个名字会被返回&quot;)</span>String username)</span>&#123;</span><br><span class="line">   <span class="keyword">return</span> username;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这样的话，可以给一些比较难理解的属性或者接口，增加一些配置信息，让人更容易阅读！</p>
<p>相较于传统的Postman或Curl方式测试接口，使用swagger简直就是傻瓜式操作，不需要额外说明文档(写得好本身就是文档)而且更不容易出错，只需要录入数据然后点击Execute，如果再配合自动化框架，可以说基本就不需要人为操作了。</p>
<p>Swagger是个优秀的工具，现在国内已经有很多的中小型互联网公司都在使用它，相较于传统的要先出Word接口文档再测试的方式，显然这样也更符合现在的快速迭代开发行情。当然了，提醒下大家在正式环境要记得关闭Swagger，一来出于安全考虑二来也可以节省运行时内存。</p>
<h4 id="3-7、拓展：其他皮肤"><a href="#3-7、拓展：其他皮肤" class="headerlink" title="3.7、拓展：其他皮肤"></a>3.7、拓展：其他皮肤</h4><p>我们可以导入不同的包实现不同的皮肤定义：</p>
<p>1、默认的   <strong>访问</strong> <strong><a target="_blank" rel="noopener" href="http://localhost:8080/swagger-ui.html">http://localhost:8080/swagger-ui.html</a></strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">   &lt;groupId&gt;io.springfox&lt;/groupId&gt;</span><br><span class="line">   &lt;artifactId&gt;springfox-swagger-ui&lt;/artifactId&gt;</span><br><span class="line">   &lt;version&gt;2.9.2&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>

<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464702-154bdb29-e615-421b-96a0-7a65020e6f58.png" fancybox="true"/></div></div>

<p>2、bootstrap-ui  <strong>访问</strong> <strong><a target="_blank" rel="noopener" href="http://localhost:8080/doc.html">http://localhost:8080/doc.html</a></strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 引入swagger-bootstrap-ui包 /doc.html--&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">   &lt;groupId&gt;com.github.xiaoymin&lt;/groupId&gt;</span><br><span class="line">   &lt;artifactId&gt;swagger-bootstrap-ui&lt;/artifactId&gt;</span><br><span class="line">   &lt;version&gt;1.9.1&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>

<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464785-0cf4291f-5d64-4623-bcab-652e579ffd4b.png" fancybox="true"/></div></div>

<p>3、Layui-ui   <strong>访问</strong> <strong><a target="_blank" rel="noopener" href="http://localhost:8080/docs.html">http://localhost:8080/docs.html</a></strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 引入swagger-ui-layer包 /docs.html--&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">   &lt;groupId&gt;com.github.caspar-chen&lt;/groupId&gt;</span><br><span class="line">   &lt;artifactId&gt;swagger-ui-layer&lt;/artifactId&gt;</span><br><span class="line">   &lt;version&gt;1.1.3&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>

<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1685868464807-5270bd80-86aa-4e19-8b07-2ae6e732f97f.png" fancybox="true"/></div></div>

<p>4、mg-ui   <strong>访问</strong> <strong><a target="_blank" rel="noopener" href="http://localhost:8080/document.html">http://localhost:8080/document.html</a></strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 引入swagger-ui-layer包 /document.html--&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">   &lt;groupId&gt;com.zyplayer&lt;/groupId&gt;</span><br><span class="line">   &lt;artifactId&gt;swagger-mg-ui&lt;/artifactId&gt;</span><br><span class="line">   &lt;version&gt;1.0.6&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>




</article>

<div class="related-wrap reveal" id="read-next"><section class="body"><div class="item" id="prev"><div class="note">较新文章</div><a href="/2023/10/05/%E7%AE%97%E6%B3%95%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA%E6%B5%8B%E8%AF%95/">算法输入输出测试</a></div><div class="item" id="next"><div class="note">较早文章</div><a href="/2023/10/05/Spring-Cloud-Gateway%E8%AF%A6%E8%A7%A3/">Spring Cloud Gateway详解</a></div></section></div>






  <div class='related-wrap md-text reveal' id="comments">
    <section class='header cmt-title cap theme'>
      快来参与讨论吧
    </section>
    <section class='body cmt-body giscus'>
      

<svg class="loading" style="vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2709"><path d="M832 512c0-176-144-320-320-320V128c211.2 0 384 172.8 384 384h-64zM192 512c0 176 144 320 320 320v64C300.8 896 128 723.2 128 512h64z" p-id="2710"></path></svg>

<div id="giscus" data-repo="echoalways/giscus" data-repo-id="R_kgDOKjJRiQ" data-category="Announcements" data-category-id="DIC_kwDOKjJRic4CaUxu" data-mapping="pathname" data-strict="0" data-reactions-enabled="1" data-emit-metadata="0" data-input-position="top" data-theme="preferred_color_scheme" data-lang="zh-CN" data-loading="lazy" crossorigin="anonymous"></div>

    </section>
  </div>



      
<footer class="page-footer reveal fs12"><hr><div class="text" style="text-align:center;"><p>云无心以出岫@远岫♥</p>
<div><span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span>，<span id="busuanzi_container_site_pv">总访问量: <span id="busuanzi_value_site_pv"></span>次</span>，<span id="busuanzi_container_site_uv">访客数: <span id="busuanzi_value_site_uv"></span>人</span></div></div></footer>

<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<script>
  function createtime() {
    var now = new Date();
    var grt= new Date("10/03/2023 18:40:00");
    now.setTime(now.getTime()+250);
    days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days);
    hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours);
    if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum);
    mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;}
    seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
    snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;}
    document.getElementById("timeDate").innerHTML = "本站已运行 "+dnum+" 天 ";
    document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
  };
  setInterval("createtime()",250);
</script>

      <div class='float-panel mobile-only blur' style='display:none'>
  <button type='button' class='sidebar-toggle mobile' onclick='sidebar.toggle()'>
    <svg class="icon" style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15301"><path d="M566.407 808.3c26.9-0.1 49.3-20.8 51.6-47.6-1.9-27.7-23.9-49.7-51.6-51.6h-412.6c-28.2-1.4-52.6 19.5-55.5 47.6 2.3 26.8 24.6 47.5 51.6 47.6h416.5v4z m309.3-249.9c26.9-0.1 49.3-20.8 51.6-47.6-2.2-26.8-24.6-47.5-51.6-47.6h-721.9c-27.7-2.8-52.5 17.4-55.3 45.1-0.1 0.8-0.1 1.7-0.2 2.5 0.9 27.2 23.6 48.5 50.7 47.6H875.707z m-103.1-245.9c26.9-0.1 49.3-20.8 51.6-47.6-0.4-28.3-23.2-51.1-51.5-51.6h-618.9c-29.5-1.1-54.3 21.9-55.5 51.4v0.2c1.4 27.8 25.2 49.2 53 47.8 0.8 0 1.7-0.1 2.5-0.2h618.8z" p-id="15302"></path><path d="M566.407 808.3c26.9-0.1 49.3-20.8 51.6-47.6-1.9-27.7-23.9-49.7-51.6-51.6h-412.6c-28.2-1.4-52.6 19.5-55.5 47.6 1.9 27.7 23.9 49.7 51.6 51.6h416.5z m309.3-249.9c26.9-0.1 49.3-20.8 51.6-47.6-2.2-26.8-24.6-47.5-51.6-47.6h-721.9c-27.7-2.8-52.5 17.4-55.3 45.1-0.1 0.8-0.1 1.7-0.2 2.5 0.9 27.2 23.6 48.5 50.7 47.6H875.707z m-103.1-245.9c26.9-0.1 49.3-20.8 51.6-47.6-0.4-28.3-23.2-51.1-51.5-51.6h-618.9c-29.5-1.1-54.3 21.9-55.5 51.4v0.2c1.4 27.8 25.2 49.2 53 47.8 0.8 0 1.7-0.1 2.5-0.2h618.8z" p-id="15303"></path></svg>
  </button>
</div>

    </div>
  </div>
  <div class='scripts'>
    <script type="text/javascript">
  const stellar = {
    // 懒加载 css https://github.com/filamentgroup/loadCSS
    loadCSS: (href, before, media, attributes) => {
      var doc = window.document;
      var ss = doc.createElement("link");
      var ref;
      if (before) {
        ref = before;
      } else {
        var refs = (doc.body || doc.getElementsByTagName("head")[0]).childNodes;
        ref = refs[refs.length - 1];
      }
      var sheets = doc.styleSheets;
      if (attributes) {
        for (var attributeName in attributes) {
          if (attributes.hasOwnProperty(attributeName)) {
            ss.setAttribute(attributeName, attributes[attributeName]);
          }
        }
      }
      ss.rel = "stylesheet";
      ss.href = href;
      ss.media = "only x";
      function ready(cb) {
        if (doc.body) {
          return cb();
        }
        setTimeout(function () {
          ready(cb);
        });
      }
      ready(function () {
        ref.parentNode.insertBefore(ss, before ? ref : ref.nextSibling);
      });
      var onloadcssdefined = function (cb) {
        var resolvedHref = ss.href;
        var i = sheets.length;
        while (i--) {
          if (sheets[i].href === resolvedHref) {
            return cb();
          }
        }
        setTimeout(function () {
          onloadcssdefined(cb);
        });
      };
      function loadCB() {
        if (ss.addEventListener) {
          ss.removeEventListener("load", loadCB);
        }
        ss.media = media || "all";
      }
      if (ss.addEventListener) {
        ss.addEventListener("load", loadCB);
      }
      ss.onloadcssdefined = onloadcssdefined;
      onloadcssdefined(loadCB);
      return ss;
    },

    // 从 butterfly 和 volantis 获得灵感
    loadScript: (src, opt) => new Promise((resolve, reject) => {
      var script = document.createElement('script');
      if (src.startsWith('/')){
        src = stellar.config.root + src.substring(1);
      }
      script.src = src;
      if (opt) {
        for (let key of Object.keys(opt)) {
          script[key] = opt[key]
        }
      } else {
        // 默认异步，如果需要同步，第二个参数传入 {} 即可
        script.async = true
      }
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    }),

    // https://github.com/jerryc127/hexo-theme-butterfly
    jQuery: (fn) => {
      if (typeof jQuery === 'undefined') {
        stellar.loadScript(stellar.plugins.jQuery).then(fn)
      } else {
        fn()
      }
    }
  };
  stellar.version = '1.19.0';
  stellar.github = 'https://github.com/xaoxuu/hexo-theme-stellar/tree/1.19.0';
  stellar.config = {
    date_suffix: {
      just: '刚刚',
      min: '分钟前',
      hour: '小时前',
      day: '天前',
      month: '个月前',
    },
    root : '/',
  };

  // required plugins (only load if needs)
  stellar.plugins = {
    jQuery: 'https://gcore.jsdelivr.net/npm/jquery@3.6.2/dist/jquery.min.js'
  };

  if ('local_search') {
    stellar.search = {};
    stellar.search.service = 'local_search';
    if (stellar.search.service == 'local_search') {
      let service_obj = Object.assign({}, {"field":"all","path":"/search.json","content":true,"sort":"-date"});
      stellar.search[stellar.search.service] = service_obj;
    }
  }

  // stellar js
  stellar.plugins.stellar = Object.assign({"sites":"/js/plugins/sites.js","friends":"/js/plugins/friends.js","ghinfo":"/js/plugins/ghinfo.js","timeline":"/js/plugins/timeline.js","linkcard":"/js/plugins/linkcard.js","fcircle":"/js/plugins/fcircle.js","weibo":"/js/plugins/weibo.js"});

  stellar.plugins.marked = Object.assign("https://cdn.bootcdn.net/ajax/libs/marked/4.0.18/marked.min.js");
  // optional plugins
  if ('false' == 'true') {
    stellar.plugins.lazyload = Object.assign({"enable":false,"js":"https://gcore.jsdelivr.net/npm/vanilla-lazyload@17.8.3/dist/lazyload.min.js","transition":"blur"});
  }
  if ('true' == 'true') {
    stellar.plugins.swiper = Object.assign({"enable":true,"css":"https://unpkg.com/swiper@8.4.5/swiper-bundle.min.css","js":"https://unpkg.com/swiper@8.4.5/swiper-bundle.min.js"});
  }
  if ('' == 'true') {
    stellar.plugins.scrollreveal = Object.assign({"enable":null,"js":"https://gcore.jsdelivr.net/npm/scrollreveal@4.0.9/dist/scrollreveal.min.js","distance":"8px","duration":500,"interval":100,"scale":1});
  }
  if ('true' == 'true') {
    stellar.plugins.preload = Object.assign({"enable":true,"service":"flying_pages","instant_page":"https://gcore.jsdelivr.net/gh/volantis-x/cdn-volantis@4.1.2/js/instant_page.js","flying_pages":"https://gcore.jsdelivr.net/gh/gijo-varghese/flying-pages@2.1.2/flying-pages.min.js"});
  }
  if ('true' == 'true') {
    stellar.plugins.fancybox = Object.assign({"enable":true,"js":"https://gcore.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.umd.js","css":"https://gcore.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.css","selector":".swiper-slide img"});
  }
  if ('false' == 'true') {
    stellar.plugins.heti = Object.assign({"enable":false,"css":"https://unpkg.com/heti@0.9.2/umd/heti.min.css","js":"https://unpkg.com/heti@0.9.2/umd/heti-addon.min.js"});
  }
  if ('true' == 'true') {
    stellar.plugins.copycode = Object.assign({"enable":true,"js":"/js/plugins/copycode.js","default_text":"Copy","success_text":"Copied"});
  }
</script>

<!-- required -->

  
<script src="/js/main.js" async></script>



<!-- optional -->

  <script>
  function loadJS() {
    const els = document.querySelectorAll("#comments #giscus");
    if (els.length === 0) return;
    els.forEach((el, i) => {
      try {
        el.innerHTML = '';
      } catch (error) {
        console.log(error);
      }
      var script = document.createElement('script');
      script.src = 'https://giscus.app/client.js';
      script.async = true;
      for (let key of Object.keys(el.attributes)) {
        let attr = el.attributes[key];
        if (['class', 'id'].includes(attr.name) === false) {
          script.setAttribute(attr.name, attr.value);
        }
      }
      el.appendChild(script);
    });
  }
  window.addEventListener('DOMContentLoaded', (event) => {
    loadJS();
  });
</script>




<!-- inject -->


  </div>
</body>
</html>
